using System;
using System.IO;
using SevenZip.Compression.LZMA;
using SevenZSharp.Engines;

namespace SevenZSharp.Decoders
{
   /// <summary>
   /// 
   /// </summary>
   public class LzmaDecoder : ShellDecoder
   {
      /// <summary>
      /// 
      /// </summary>
      /// <param name="engine"></param>
      public LzmaDecoder(ShellEngine engine)
         : base(engine)
      {
      }

      /// <summary>
      /// 
      /// </summary>
      /// <param name="inFile"></param>
      /// <param name="outFile"></param>
      public override void DecodeSingleFile(string inFile, string outFile)
      {
         using (FileStream inStream = new FileStream(inFile, FileMode.Open, FileAccess.Read))
         {
            using (FileStream outStream = new FileStream(outFile, FileMode.OpenOrCreate, FileAccess.Write))
            {
               DecodeSingleFile(inStream, outStream);
            }
         }
      }

      /// <summary>
      /// Decodes a single file. <paramref name="inStream"/> is the
      /// encoded file which will be decoded into <paramref name="outStream"/>.
      /// If <paramref name="outStream"/> does not exist, it will be created.
      /// </summary>
      /// <param name="inStream">The in stream.</param>
      /// <param name="outStream">The out stream.</param>
      public override void DecodeSingleFile(FileStream inStream, FileStream outStream)
      {
         byte[] properties = new byte[5];
         if (inStream.Read(properties, 0, 5) != 5)
         {
            throw (new Exception("input .lzma is too short"));
         }

         Decoder decoder = new Decoder();
         decoder.SetDecoderProperties(properties);
         long outSize = 0;

         for (int i = 0; i < 8; i++)
         {
            int v = inStream.ReadByte();
            if (v < 0)
            {
               throw (new Exception("Can't Read 1"));
            }
            outSize |= ((long) (byte) v) << (8*i);
         }

         long compressedSize = inStream.Length - inStream.Position;
         decoder.Code(inStream, outStream, compressedSize, outSize, null);
      }
   }
}